// 路由守卫 + 权限控制
import router from '@/router'
import store from '@/store'
import nprogress from 'nprogress'
import 'nprogress/nprogress.css'

// 导入动态路由表数组
import { asyncRoutes } from '@/router'

// 白名单
const whiteList = ['/login', '/404']

// 全局前置守卫 - 跳转前
router.beforeEach(async (to, from, next) => {
  // 跳转前开启进度条
  nprogress.start()
  // 从vuex中取出token
  const { token } = store.state.user
  if (token) { // 已登录
    if (to.path === '/login') { // 还要去登录
      next('/')// 导航去首页
      // 跳转后关闭进度条
      nprogress.done()
    } else {
      try {
        // 如果没有userId,则发起第1次请求
        if (!store.state.user.userInfo.userId) {
          // 1. 调用vuex中的获取用户信息的action函数
          const userInfo = await store.dispatch('user/getUserInfoAction')
          // 2. 根据角色的菜单权限开放相应的左侧菜单(todo)
          // 2.1 拿到menus数组，menus包含当前用户拥有的菜单权限
          const { menus } = userInfo.roles
          // 2.2 基于menus筛选动态路由表
          const filteredAsyncRoutes = asyncRoutes.filter(
            item => menus.includes(item.children[0].name)
          )
          // 2.3 调用router.addRoutes()追加新的路由规则(这样才可以访问)
          //     末尾补充 path为* 的规则
          router.addRoutes([
            ...filteredAsyncRoutes,
            {
              path: '*',
              redirect: '/404',
              hidden: true
            }
          ])
          // 2.4 调用user模块setRoutes()追加到vuex中
          store.commit('user/setRoutes', filteredAsyncRoutes)

          // router.push()
          // router.replace()

          // 2.5 重新进入一次(放行) - 避免刷新后白屏
          // next(to.path)
          // 推荐的写法
          next({
            // 保留to原有的所有属性
            ...to,
            // 替换上一次的路由历史记录
            replace: true
          })
          // 问题：菜单中有路由页面能访问，因为调用了addRoutes()，但是左侧菜单名称并没有相应的
          //      同步，原因是左侧菜单获取的数据是 this.$router.option.routes，这个数据不
          //      是响应式的，所以就算调用了addRoutes()，这个数据并没有变，渲染的仍然是静态路由表
        } else {
          // 直接放行
          next()
        }
        // eslint-disable-next-line no-empty
      } catch (err) {
      }
    }
  } else { // 未登录
    if (whiteList.includes(to.path)) { // 要访问白名单路由
      next()// 放行
    } else {
      // 先去登录,并携带回跳地址
      next(`/login?redirectUrl=${to.fullPath}`)
      // 跳转后关闭进度条
      nprogress.done()
    }
  }
})

// 全局后置守卫 - 跳转后
router.afterEach(() => {
  // 跳转后关闭进度条
  nprogress.done()
})
